import re

from QQLoginTool.QQtool import OAuthQQ
from django import http
from django.conf import settings
from django.contrib.auth import login
from django.db import DatabaseError
from django.shortcuts import render, redirect
import logging
# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from carts.utils import merge_cart_cookie_to_redis
from meiduo_mall.utils.response_code import RETCODE
from oauth.models import OAuthQQUser
from oauth.utils import *
from users.models import User

logger = logging.getLogger('django')


class OAuthURLView(View):
    """用于返回qq的登陆url"""
    def get(self, request):
        # 当用户在前端点击QQ按钮时，前端会自动拼接如下的路径：前面一部分的路由已经有了，需要截取后面next部分的查询字符串；
        # this.host + '/qq/authorization/?next=' + next;
        next = request.GET.get('next')

        # 初始化oauth对象:参数说明：client_id：appid，client_secret：'app key'
        # redirect_uri：登录成功后的回调url，state：记录当前跳转界面的来源
        ouath = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=next)

        # 调用SDK中get_qq_url方法得到拼接好的qq登陆扫描页面，需要返回给到前端首页响应；
        login_url = ouath.get_qq_url()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})


class OAuthUserView(View):
    """拿到回调地址后的处理"""
    def get(self, request):
        # 获取回调url中的相关参数，当用户进行扫码后才能拿到回调地址，此时才出现code;
        code = request.GET.get('code')
        if code is None:
            return http.HttpResponseForbidden('缺少参数code')

        # 初始化对象
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI
           )

        try:
            # 传入code值，获得access_token
            access_token = oauth.get_access_token(code)
            # 通过access_token获取到openid
            openid = oauth.get_open_id(access_token)
        except Exception as er:
            logger.error(er)
            return http.HttpResponseServerError('QQ登陆失败')

        # 查询数据库中是否存在openid;
        # 如果已绑1)获取user,实现状态保持；2）创建响应对象，并重定向到之前的页面；3）设置cookie；4）将cookie中获取的username展示出来；
        # 如果未绑定,则返回绑定界面；
        # 对ipenid进行加密
        try:
            oauth_model = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            openid = generate_openid_signature(openid)
            return render(request, 'oauth_callback.html', {'openid': openid})

        else:
            user = oauth_model.user  # 此处通过外健获取user
            login(request, user)
            response = redirect(request.GET.get('state') or "/")
            response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
            return response

    def post(self, request):
        """当用户拿到绑定页面页面点击提交时发起的post请求"""
        # 获取前端表单请求的表单数据；

        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        openid = request.POST.get('openid')
        # 校验获取的参数1）是否参数全；2）手机号码是不是对的，密码是不是对的；4）短信验证码是不是对的；
        # 校验手机号码是不是已存在；
        if all([mobile, password, sms_code_client, openid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        if not re.match(r'^1[345789]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')

        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20位的密码')

        # 连接数据库提取出短信验证码，并与用户输入的进行对比；
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_code_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg':'短信验证码过期'})

        if sms_code_client.lower() != sms_code_server.decode().lower():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '短信验证码输入错误'})

        # 需要解密
        openid = check_openid(openid)
        if openid is None:
            return render(request, 'oauth_callback.html', {'openid_errmsg', 'openid无效'})

        # 1）已存在，则为老用户；校验密码是不是对的；
        try:
            user = User.objects.get(mobile=mobile)
            if not user.check_password(password):
                return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})

        # 2）不存在，则为新用户，在数据库的用户表中和openi表中均写入数据；
        except User.DoesNotExist:
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)

        try:
            OAuthQQUser.objects.create(openid=openid, user=user)
        except DatabaseError:
            return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登陆失败'})

        # 3）用户保持状态，拼接响应对象（需要重定向到用户之前的登陆界面），设置session,返回给到前端；
        login(request, user)
        response = redirect(request.GET.get('state') or '/')
        response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
        # 合并购物车的数据
        merge_cart_cookie_to_redis(request,response)
        return response











